home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume3 / pcmail / part05 < prev    next >
Encoding:
Internet Message Format  |  1989-02-03  |  58.0 KB

  1. Path: xanth!mcnc!ncsuvx!lll-winken!lll-tis!ames!necntc!ncoast!allbery
  2. From: wswietse@eutrc3.UUCP (Wietse Venema)
  3. Newsgroups: comp.sources.misc
  4. Subject: v03i006: uucp mail for pc's (5 of 8)
  5. Message-ID: <214@eutrc3.UUCP>
  6. Date: 20 Apr 88 16:50:16 GMT
  7. Sender: allbery@ncoast.UUCP
  8. Reply-To: wswietse@eutrc3.UUCP (Wietse Venema)
  9. Organization: Tech. Univ. Eindhoven, Neth.
  10. Lines: 2164
  11. Approved: allbery@ncoast.UUCP
  12.  
  13. comp.sources.misc: Volume 3, Issue 6
  14. Submitted-By: "Wietse Venema" <wswietse@eutrc3.UUCP>
  15. Archive-Name: pcmail/Part5
  16.  
  17. #! /bin/sh
  18. # This is a shell archive.  Remove anything before this line, then unpack
  19. # it by saving it into a file and typing "sh file".  To overwrite existing
  20. # files, type "sh file -c".  You can also feed this as standard input via
  21. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  22. # will see the following message at the end:
  23. #        "End of archive 5 (of 8)."
  24. # Contents:  ascf.c comm.h deskutil.c invoke.c kpres.c logs.c path.h
  25. #   sendwork.c spoolfil.c srctoman.sh switcher.c unalias.c
  26. # Wrapped by wietse@eutwc1 on Wed Apr 20 16:45:27 1988
  27. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  28. if test -f ascf.c -a "${1}" != "-c" ; then 
  29.   echo shar: Will not over-write existing file \"ascf.c\"
  30. else
  31. echo shar: Extracting \"ascf.c\" \(4105 characters\)
  32. sed "s/^X//" >ascf.c <<'END_OF_ascf.c'
  33. X/*++
  34. X/* NAME
  35. X/*    ascf 3
  36. X/* SUMMARY
  37. X/*    stdio-like ascii filter
  38. X/* PROJECT
  39. X/*    pc-mail
  40. X/* PACKAGE
  41. X/*    ascii filtering
  42. X/* SYNOPSIS
  43. X/*    FILE *ascopen(name,mode)
  44. X/*    char *name;
  45. X/*    char *mode;
  46. X/*
  47. X/*    int ascget(fp)
  48. X/*    FILE *fp;
  49. X/*
  50. X/*    int ascclose(fp)
  51. X/*    FILE *fp;
  52. X/* DESCRIPTION
  53. X/*    The functions in this module provide filtered stream i/o for
  54. X/*    textfiles produced by word processors. Their calling sequence
  55. X/*    has been modelled after the standard i/o library routines.
  56. X/*
  57. X/*    ascopen() is the analogon of fopen(3), ascget() returns the next
  58. X/*    character in the filtered input stream, and ascclose() closes 
  59. X/*    the stream. ascget() is a macro.
  60. X/*
  61. X/*    The following mappings are done: cr/lf, cr, lf, lf/cr are 
  62. X/*    replaced by newline; all high bits are stripped off; wordstar
  63. X/*    hyphens are converted to normal hyphens. Except for tabs,
  64. X/*    all control characters are suppressed in the output.
  65. X/*    In order to avoid problems in mailers, a newline
  66. X/*    character is appended to the last line of each file.
  67. X/* SEE ALSO
  68. X/*    stdio(3)    standard i/o library interface.
  69. X/* DIAGNOSTICS
  70. X/*    ascopen() returns a null pointer on failure; ascget() returns
  71. X/*    the value EOF when the end of a stream is reached. ascclose()
  72. X/*    returns whatever fclose() returns.
  73. X/* BUGS
  74. X/*    Actually works with wordstar or clean ascii files only.
  75. X/*    No character pushback.
  76. X/*    Although allowed by ascopen(), the "w" file open mode is 
  77. X/*    of no use. 
  78. X/* AUTHOR(S)
  79. X/*    W.Z. Venema
  80. X/*    Eindhoven University of Technology
  81. X/*    Department of Mathematics and Computer Science
  82. X/*    Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  83. X/* CREATION DATE
  84. X/*    Mon Jul  6 16:03:41 GMT+1:00 1987
  85. X/* LAST MODIFICATION
  86. X/*    Mon Apr  4 23:34:46 MET 1988
  87. X/* VERSION/RELEASE
  88. X/*    1.4
  89. X/*--*/
  90. X
  91. X#include <ctype.h>
  92. X
  93. X#include "defs.h"
  94. X#include "ascf.h"
  95. X
  96. X/* some systems do not define _NFILE in stdio.h */
  97. X
  98. X#ifndef _NFILE
  99. X#  include <sys/param.h>        /* maybe we are a sun */
  100. X#    ifdef NOFILE
  101. X#    define _NFILE NOFILE
  102. X#  else
  103. X"ERROR: cannot get max nr of open files"
  104. X#  endif
  105. X#endif
  106. X
  107. X#define CTRL(x) ((x)^0100)        /* ASCII control characters */
  108. X
  109. X#ifdef MSDOS
  110. X#include <fcntl.h>            /* to turn cr/lf mapping off */
  111. X#endif
  112. X
  113. Xpublic Asc asc[_NFILE];            /* one filter structure per file */
  114. X
  115. X/* ascopen - open stream, initialize intermediate buffer */
  116. X
  117. Xpublic FILE *ascopen(file,mode)
  118. Xchar *file,*mode;
  119. X{
  120. X    register FILE *fp;
  121. X
  122. X    if (fp = fopen(file,mode)) {    /* if file is accessable */
  123. X    register Asc *ap = asc+fileno(fp);
  124. X    if (ap->buf = malloc(BUFSIZ)) {    /* if buffer available */
  125. X        ap->cnt = 0;        /* init buffer count */
  126. X        ap->nlf = 0;        /* no newline appended yet */
  127. X#ifdef O_BINARY
  128. X        setmode(fileno(fp),O_BINARY);
  129. X#endif
  130. X    } else {
  131. X        fclose(fp);            /* no room for that buffer */
  132. X        fp = 0;
  133. X     }
  134. X    }
  135. X    return(fp);
  136. X}
  137. X
  138. X/* ascclose - release intermediate buffer and close the stream */
  139. X
  140. Xpublic int ascclose(fp)
  141. Xregister FILE *fp;
  142. X{
  143. X    free(asc[fileno(fp)].buf);
  144. X    return(fclose(fp));
  145. X}
  146. X
  147. X/* ascbuf - ascii filter, make new buffer of text */
  148. X
  149. Xpublic int ascbuf(fp)
  150. XFILE *fp;
  151. X{
  152. X    register Asc *ap = asc+fileno(fp);    /* intermediate buffer access */
  153. X    register char *cp = ap->buf;    /* init write pointer */
  154. X    register int c;            /* single-character input buffer */
  155. X    int d;                /* look-ahead character */
  156. X
  157. X    while (cp < ap->buf+BUFSIZ && 
  158. X    (c = getc(fp)) != EOF && (c &= 0177) != CTRL('Z')) {
  159. X    if (c == ' ' || isprint(c) || c == '\t') {
  160. X        *cp++ = c;            /* accept character */
  161. X    } else if ((c == '\r' && ((d = getc(fp)) == '\n' || (ungetc(d,fp),1)))
  162. X        || (c == '\n' && ((d = getc(fp)) == '\r' || (ungetc(d,fp),1)))) {
  163. X        *cp++ = '\n';        /* terminate line */
  164. X    } else if (c == CTRL('_')) {
  165. X        *cp++ = '-';        /* wordstar hyphen */
  166. X    } else {
  167. X        continue;            /* ignore other characters */
  168. X    }
  169. X    }
  170. X    if (ap->cnt = cp-ap->buf) {        /* anything in the buffer? */
  171. X    ap->ptr = ap->buf;        /* yes, set read pointer */
  172. X    return(ascget(fp));        /* and return first character */
  173. X    } else if (ap->nlf == 0) {        /* make sure file ends with \n */
  174. X        return(ap->nlf = '\n');        /* append newline first */
  175. X    } else {                /* now we're really done */
  176. X    return(EOF);            /* that's it. */
  177. X    }
  178. X}
  179. END_OF_ascf.c
  180. if test 4105 -ne `wc -c <ascf.c`; then
  181.     echo shar: \"ascf.c\" unpacked with wrong size!
  182. fi
  183. # end of overwriting check
  184. fi
  185. if test -f comm.h -a "${1}" != "-c" ; then 
  186.   echo shar: Will not over-write existing file \"comm.h\"
  187. else
  188. echo shar: Extracting \"comm.h\" \(1967 characters\)
  189. sed "s/^X//" >comm.h <<'END_OF_comm.h'
  190. X/*++
  191. X/* NAME
  192. X/*      comm 5
  193. X/* SUMMARY
  194. X/*      cico systems parameters
  195. X/* PROJECT
  196. X/*      pc-mail
  197. X/* PACKAGE
  198. X/*      cico
  199. X/* SYNOPSIS
  200. X/*      #include "params.h"
  201. X/*      #include "comm.h"
  202. X/* DESCRIPTION
  203. X/* .nf
  204. X
  205. X/* /* roles and other behavioural codes */
  206. X
  207. X#define MASTER    1            /* who sends files */
  208. X#define SLAVE    2            /* who receives files */
  209. X#define DONE    3            /* no more files */
  210. X
  211. X#define YES    'Y'
  212. X#define NO    'N'
  213. X
  214. X/* /* communications parameters (see params.h) */
  215. X
  216. X#define COMM_LINE    (comm[P_PORT].strval)
  217. X#define COMM_RATE    (comm[P_BAUD].strval)
  218. X#define DIAL_SEQUENCE    (comm[P_DIAL].strval)
  219. X#define LOGIN_NAME    (comm[P_LOGIN].strval)  
  220. X#define DISC_SEQUENCE    (comm[P_DISC].strval)
  221. X
  222. X/* /* related info */
  223. X
  224. Xextern int ttfd;            /* comm. port */
  225. Xextern Info *comm;            /* comm. info */
  226. Xextern char *password;            /* password */
  227. Xextern char rmthost[];            /* remote system name */
  228. X
  229. X/* /* functions that use the above */
  230. X
  231. Xextern char *rmtname();            /* make remote spool-file name */
  232. Xextern char *locname();            /* make local spool-file name */
  233. X
  234. X/* /* protocol function pointers */
  235. X
  236. Xextern int (*Read)();            /* protocol read */
  237. Xextern int (*Write)();            /* protocol write */
  238. Xextern int (*Close)();            /* protocol close */
  239. X
  240. X/* /* use these at your own risk */
  241. X
  242. X#define MSGBUF       4096        /* message buffer size */
  243. X
  244. Xextern char msgin[MSGBUF];        /* message receive buffer */
  245. Xextern char msgout[MSGBUF];        /* message send buffer */
  246. X
  247. X/* /* message i/o functions */
  248. X
  249. Xextern int isok();            /* do request; get yes or no */
  250. Xextern char *talk();            /* send message */
  251. Xextern char *hear();            /* receive message */
  252. X/* SEE ALSO
  253. X/*      comm(3) implementation module
  254. X/* AUTHOR(S)
  255. X/*      W.Z. Venema
  256. X/*      Eindhoven University of Technology
  257. X/*      Department of Mathematics and Computer Science
  258. X/*      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  259. X/* CREATION DATE
  260. X/*      Sun Apr 12 13:52:39 GMT+1:00 1987
  261. X/* LAST MODIFICATION
  262. X/*    Mon Apr  4 23:36:42 MET 1988
  263. X/* VERSION/RELEASE
  264. X/*    1.3
  265. X/*--*/
  266. END_OF_comm.h
  267. if test 1967 -ne `wc -c <comm.h`; then
  268.     echo shar: \"comm.h\" unpacked with wrong size!
  269. fi
  270. # end of overwriting check
  271. fi
  272. if test -f deskutil.c -a "${1}" != "-c" ; then 
  273.   echo shar: Will not over-write existing file \"deskutil.c\"
  274. else
  275. echo shar: Extracting \"deskutil.c\" \(4943 characters\)
  276. sed "s/^X//" >deskutil.c <<'END_OF_deskutil.c'
  277. X/*++
  278. X/* NAME
  279. X/*    deskutil 3
  280. X/* SUMMARY
  281. X/*    utility functions
  282. X/* PROJECT
  283. X/*    pc-mail
  284. X/* PACKAGE
  285. X/*    mailsh
  286. X/* SYNOPSIS
  287. X/*    #include "mailsh.h"
  288. X/*
  289. X/*    void patience()
  290. X/*
  291. X/*    int when()
  292. X/*
  293. X/*    int delete()
  294. X/*
  295. X/*    int unspool()
  296. X/*
  297. X/*    int print()
  298. X/*
  299. X/*    int save()
  300. X/*
  301. X/*    char *tstamp(ltime)
  302. X/*    long *ltime()
  303. X/* DESCRIPTION
  304. X/*    tstamp() converts absolute time to a string. If called with
  305. X/*    recent time argument (less than 100 days ago) the string will
  306. X/*    be of the form "Sun Apr 17 12:50", otherwise "Sun Apr 17  1988".
  307. X/*
  308. X/*      delete() gives the user another chance before a message is deleted.
  309. X/*
  310. X/*      unspool() actually deletes a message. As a side effect it destroys
  311. X/*      the current mail box display so that the next display will
  312. X/*    reflect the actual status of the spool directory.
  313. X/*    The affected message and meta file names are taken from the
  314. X/*    global "message" and "commant" string variables.
  315. X/*
  316. X/*    print() copies a pager file to the printer.
  317. X/*
  318. X/*    save() asks where the pager file should be saved.
  319. X/*
  320. X/*    when() should be called after the user has entered a mail destination
  321. X/*    address. It informs the user that messages are not sent right away, 
  322. X/*    but after selection of the Network option in the main menu.
  323. X/*
  324. X/*    patience() prints a 'one moment please' message in the middle
  325. X/*    screen window. As a side effect, the current pager file is set
  326. X/*    to none.
  327. X/* FILES
  328. X/*      mail header files in the spool directory
  329. X/* SEE ALSO
  330. X/*      pager(3), pager(5), kbdinp(3)
  331. X/* AUTHOR(S)
  332. X/*      W.Z. Venema
  333. X/*      Eindhoven University of Technology
  334. X/*      Department of Mathematics and Computer Science
  335. X/*      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  336. X/* CREATION DATE
  337. X/*    Tue May 12 15:35:20 GMT+1:00 1987
  338. X/* LAST MODIFICATION
  339. X/*    Mon Apr  4 23:38:26 MET 1988
  340. X/* VERSION/RELEASE
  341. X/*    1.3
  342. X/*--*/
  343. X
  344. X#include <errno.h>
  345. X
  346. X#include "defs.h"
  347. X#include "pager.h"
  348. X#include "mailsh.h"
  349. X#include "screen.h"
  350. X#include "status.h"
  351. X
  352. Xhidden int save_desk();
  353. X
  354. X/* patience - say this will take some time */
  355. X
  356. Xpublic void patience()
  357. X{
  358. X    static char *m_wait[] = {
  359. X    "",
  360. X    "One moment please...",
  361. X    0,
  362. X    };
  363. X
  364. X    register File *pp = open_pager();        /* create pager file */
  365. X
  366. X    mesg_pager(pp,m_wait);            /* write pager file */
  367. X    ds_pager();                    /* show om middle window */
  368. X    close_pager(pp);                /* forget pager file */
  369. X}
  370. X
  371. X/* delete - user wants to delete a message; ask for confirmation */
  372. X
  373. Xpublic int delete()
  374. X{
  375. X    static Screen screen[] = {
  376. X    ESCCR,    "Enter",    unspool,int_error,
  377. X    0,    0,        0,
  378. X    "Press ESC to cancel. Confirm with ENTER",
  379. X    };
  380. X
  381. X    return(kbdinp(screen)|S_REDRAW);
  382. X}
  383. X
  384. X/* unspool - actually delete a message; force mail box display rebuild */
  385. X
  386. Xpublic int unspool()
  387. X{
  388. X    if (((chmod(message,0666) || unlink(message)) && errno != ENOENT)
  389. X    || ((chmod(comment,0666) || unlink(comment)) && errno != ENOENT)) {
  390. X    errdisp(E_UNLINK);            /* notify user of problem */
  391. X    return(S_REDRAW);            /* say screen has changed */
  392. X    } else {
  393. X    junk_desk();                /* say mail box has changed */
  394. X    return(S_BREAK);            /* no more work to do */
  395. X    }
  396. X}
  397. X
  398. X/* print - print pager display on default printer */
  399. X
  400. Xpublic int print()
  401. X{
  402. X    return(pr_pager() ? (errdisp(E_PRINTERR),S_REDRAW) : 0);
  403. X}
  404. X
  405. X/* save - ask where pager display should be copied to */
  406. X
  407. Xpublic int save()
  408. X{
  409. X    static Screen screen[] = {
  410. X    STRING,    0,              save_desk,int_error,
  411. X    0,    0,              0,
  412. X    "Press ESC to cancel. Save to file:",
  413. X    };
  414. X
  415. X    kbdinp(screen);            /* prompt for file name, then copy */
  416. X    return(S_REDRAW);            /* force screen repaint */
  417. X}
  418. X
  419. X/* save_desk - copy pager file to ordinary file */
  420. X
  421. Xhidden int save_desk(to)
  422. Xchar *to;
  423. X{
  424. X    if (cp_pager(to)) {            /* if file copy failed */
  425. X    unlink(to);            /* remove that file */
  426. X    errdisp(E_WRITERR);        /* notify the user */
  427. X    return(S_BREAK|S_REDRAW);    /* redisplay, terminate caller */
  428. X    } else {
  429. X    junk_file();            /* say file display maybe outdated */
  430. X    return(S_BREAK);        /* terminate caller */
  431. X    }
  432. X}
  433. X
  434. X/* when - say when mail will actually be sent */
  435. X
  436. Xpublic int when()
  437. X{
  438. X    static char *msg[] = {
  439. X    "",
  440. X    "To send messages through the network, use the Network",
  441. X    "option in the main menu.",
  442. X    0,
  443. X    };
  444. X    File *pp = open_pager();            /* open new pager file */
  445. X
  446. X    mesg_pager(pp,msg);                /* fill pager file */
  447. X    ds_pager();                    /* display the file */
  448. X    close_pager(pp);                /* forget pager file */
  449. X    return(0);                    /* don't care value */
  450. X}
  451. X
  452. X/* tstamp - time format as produced by the ls(1) command */
  453. X
  454. Xpublic char *tstamp(ltime)
  455. Xlong *ltime;
  456. X{
  457. X    static char buf[25];
  458. X
  459. X    /*
  460. X    * Output from asctime() is of the form
  461. X    *    "Sun Apr 17 13:34:35 1988"
  462. X    * Depending on how recent the time in question is, we
  463. X    * supress the time or year field.
  464. X    */
  465. X
  466. X    (void) strcpy(buf,asctime(localtime(ltime)));
  467. X    if (time((long *)0)-*ltime > 60L*60L*24L*100L) {
  468. X    buf[24] = '\0';                /* remove the \n */
  469. X    (void) strcpy(buf+11,buf+19);        /* old file, show year */
  470. X    } else
  471. X    buf[16] = '\0';                /* recent, show time */
  472. X    return(buf);
  473. X}
  474. END_OF_deskutil.c
  475. if test 4943 -ne `wc -c <deskutil.c`; then
  476.     echo shar: \"deskutil.c\" unpacked with wrong size!
  477. fi
  478. # end of overwriting check
  479. fi
  480. if test -f invoke.c -a "${1}" != "-c" ; then 
  481.   echo shar: Will not over-write existing file \"invoke.c\"
  482. else
  483. echo shar: Extracting \"invoke.c\" \(4946 characters\)
  484. sed "s/^X//" >invoke.c <<'END_OF_invoke.c'
  485. X/*++
  486. X/* NAME
  487. X/*      invoke 3
  488. X/* SUMMARY
  489. X/*      system-dependent process control stuff
  490. X/* PROJECT
  491. X/*      pc-mail
  492. X/* PACKAGE
  493. X/*      mailsh
  494. X/* SYNOPSIS
  495. X/*      #include "status.h"
  496. X/*
  497. X/*    int invokelp(arg0,arg1,...)
  498. X/*      char *arg0,*arg1,...
  499. X/*
  500. X/*    int invokevp(argv)
  501. X/*    char **argv;
  502. X/*
  503. X/*    int onexit(command)
  504. X/*    char *command;
  505. X/* DESCRIPTION
  506. X/*      invokelp() creates a child process to execute a command.
  507. X/*      arg0, arg1,... is a null-terminated list of string pointers,
  508. X/*    the first being the name of the program. Use is made
  509. X/*    of the search path to locate the program in arg0.
  510. X/*
  511. X/*    invokevp() is similar to invokelp; the difference is that
  512. X/*    argv is an array of pointers to arguments.
  513. X/*
  514. X/*    onexit() executes a command, thereby terminating the current process.
  515. X/* DIAGNOSTICS
  516. X/*    invokelp(), invokevp() return the exit status of the child process, 
  517. X/*    E_SYSFAIL if there were insufficient resources, and
  518. X/*    E_NOPROG if the program in arg0 or argv[0] could not be found.
  519. X/*
  520. X/*    onexit() return -1 if there were problems.
  521. X/* BUGS
  522. X/*    The invokexx() functions should not be used if the command needs to 
  523. X/*    be handled by a command-language processor (e.g. shell built-ins,
  524. X/*    or i/o redirection).
  525. X/* AUTHOR(S)
  526. X/*      W.Z. Venema
  527. X/*      Eindhoven University of Technology
  528. X/*      Department of Mathematics and Computer Science
  529. X/*      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  530. X/* CREATION DATE
  531. X/*      Sun Apr  5 15:27:37 GMT+1:00 1987
  532. X/* LAST MODIFICATION
  533. X/*    Wed Apr  6 00:19:56 MET 1988
  534. X/* VERSION/RELEASE
  535. X/*    1.4
  536. X/*--*/
  537. X
  538. X#include <errno.h>
  539. X#include "defs.h"
  540. X#include "status.h"
  541. X
  542. X#ifdef  MSDOS
  543. X#include <process.h>
  544. X#endif
  545. X
  546. X/* invokelp - create child process to execute command */
  547. X
  548. X/* VARARGS2 */
  549. X
  550. Xpublic int invokelp(arg0,arg1,arg2,arg3,arg4)
  551. Xchar *arg0,*arg1,*arg2,*arg3,*arg4;
  552. X{
  553. X    /*
  554. X    * On unix systems we fork a process and overlay the child with
  555. X    * the desired program.
  556. X    * This means we get -1 if the fork did not succeed, otherwise
  557. X    * the exit status if the child process. The code is a bit elaborate
  558. X    * since we want to handle various error conditions.
  559. X    */
  560. X#ifdef unix
  561. X    register int pid;
  562. X
  563. X    if ((pid = fork()) < 0) {        /* fork off a process */
  564. X    return(E_SYSFAIL);        /* resources exhausted */
  565. X    } else if (pid == 0) {        /* this is the child process */
  566. X    execlp(arg0,arg0,arg1,arg2,arg3,arg4);/* try to replace it */
  567. X    _exit(errno == ENOENT ? E_NOPROG : E_SYSFAIL); /* sorry, failed */
  568. X    /* NOTREACHED */
  569. X    } else {
  570. X    int xstat,wstat;        /* wait till above child terminates */
  571. X    while ((wstat = wait(&xstat)) != -1 && wstat != pid)
  572. X        /* void */ ;
  573. X    if (wstat == -1) {
  574. X        return(E_SYSFAIL);        /* oops: no child! */
  575. X    } else if (xstat&0377) {
  576. X        return(E_UNKNOWN);        /* child was killed */
  577. X    } else {
  578. X        return(xstat>>8);        /* child died naturally */
  579. X    }
  580. X    /* NOTREACHED */
  581. X    }
  582. X#endif
  583. X
  584. X    /*
  585. X    * On MS-DOS systems we try to avoid the command.com shell because
  586. X    * it always returns a zero status code. 
  587. X    */
  588. X#ifdef MSDOS
  589. X    int stat;
  590. X    char *p;
  591. X
  592. X    if ((stat = spawnlp(P_WAIT,arg0,arg0,arg1,arg2,arg3,arg4)) < 0
  593. X    && errno == ENOENT 
  594. X    && (strcmp(p = arg0+strlen(arg0)-4,".bat") == 0 || strcmp(p,".BAT") == 0))
  595. X    stat = spawnlp(P_WAIT,"command","command","/c",arg0,arg1,arg2,arg3,arg4);
  596. X    return(stat >= 0 ? stat : (errno == ENOENT ? E_NOPROG : E_SYSFAIL));
  597. X#endif
  598. X}
  599. X
  600. X/* invokelp - create child process to execute command */
  601. X
  602. Xpublic int invokevp(argv)
  603. Xchar **argv;
  604. X{
  605. X    /*
  606. X    * On unix systems we fork a process and overlay the child with
  607. X    * the desired program.
  608. X    * This means we get -1 if the fork did not succeed, otherwise
  609. X    * the exit status if the child process. The code is a bit elaborate
  610. X    * since we want to handle various error conditions.
  611. X    */
  612. X#ifdef unix
  613. X    register int pid;
  614. X
  615. X    if ((pid = fork()) < 0) {        /* fork off a process */
  616. X    return(E_SYSFAIL);        /* resources exhausted */
  617. X    } else if (pid == 0) {        /* this is the child process */
  618. X    execvp(*argv,argv);        /* try to replace it */
  619. X    _exit(errno == ENOENT ? E_NOPROG : E_SYSFAIL); /* sorry, failed */
  620. X    /* NOTREACHED */
  621. X    } else {
  622. X    int xstat,wstat;        /* wait till above child terminates */
  623. X    while ((wstat = wait(&xstat)) != -1 && wstat != pid)
  624. X        /* void */ ;
  625. X    if (wstat == -1) {
  626. X        return(E_SYSFAIL);        /* oops: no child! */
  627. X    } else if (xstat&0377) {
  628. X        return(E_UNKNOWN);        /* child was killed */
  629. X    } else {
  630. X        return(xstat>>8);        /* child died naturally */
  631. X    }
  632. X    /* NOTREACHED */
  633. X    }
  634. X#endif
  635. X
  636. X    /*
  637. X    * On MS-DOS systems we try to avoid the command.com shell because
  638. X    * it always returns a zero status code. 
  639. X    */
  640. X#ifdef MSDOS
  641. X    int stat;
  642. X
  643. X    return((stat = spawnvp(P_WAIT,*argv,argv)) >= 0 ? 
  644. X    stat : (errno == ENOENT ? E_NOPROG : E_SYSFAIL));
  645. X#endif
  646. X}
  647. X
  648. X/* onexit - exec another command */
  649. X
  650. Xint onexit(command)
  651. Xchar *command;
  652. X{
  653. X    if (command && *command) {
  654. X#ifdef unix
  655. X    return(execlp("/bin/sh","sh","-c",command));
  656. X#endif
  657. X
  658. X#ifdef MSDOS
  659. X    return(system(command));
  660. X#endif
  661. X    }
  662. X}
  663. END_OF_invoke.c
  664. if test 4946 -ne `wc -c <invoke.c`; then
  665.     echo shar: \"invoke.c\" unpacked with wrong size!
  666. fi
  667. # end of overwriting check
  668. fi
  669. if test -f kpres.c -a "${1}" != "-c" ; then 
  670.   echo shar: Will not over-write existing file \"kpres.c\"
  671. else
  672. echo shar: Extracting \"kpres.c\" \(4951 characters\)
  673. sed "s/^X//" >kpres.c <<'END_OF_kpres.c'
  674. X/*++
  675. X/* NAME
  676. X/*    kpres
  677. X/* SUMMARY
  678. X/*    k-protocol presentation layer
  679. X/* PACKAGE
  680. X/*    uucp across thenet
  681. X/* SYNOPSIS
  682. X/*    #include "kp.h"
  683. X/*
  684. X/*    kopen(fd)
  685. X/*    int fd;
  686. X/*
  687. X/*    kwrite(fd,buf,len)
  688. X/*    int fd,len;
  689. X/*    char *buf;
  690. X/*
  691. X/*    kread(fd,buf,len)
  692. X/*    int fd,len;
  693. X/*    char *buf;
  694. X/*
  695. X/*    kclose(fd)
  696. X/*    int fd;
  697. X/* DESCRIPTION
  698. X/*    This section contains functions that imitate standard unix
  699. X/*    unbuffered i/o facilities. A status code of FAIL is returned when
  700. X/*    the network partner wants to terminate the protocol, or when the
  701. X/*    the transmission error rate is excessive.
  702. X/*
  703. X/*    Eight-bit data bytes are transported as harmless six-bit data bytes
  704. X/*    in the ASCII range 32 through 95. This introduces an overhead of 33%.
  705. X/*    For textfiles, this is hardly worse than kermit (typical overhead 
  706. X/*    10 %). For binary files the overhead is much less than with kermit 
  707. X/*    (typical overhead 60%).
  708. X/*
  709. X/*    Kopen() sets up the terminal characteristics of the specified file
  710. X/*    descriptors (no echo, raw, tandem). Always returns zero status.
  711. X/*
  712. X/*    Kwrite() attempts to send the bytes in buf. A zero-length buffer 
  713. X/*    should be written to indicate an end-of-file condition. Return status: 
  714. X/*    the number of bytes requested, or FAIL.
  715. X/*
  716. X/*    Kread() attempts to read the requested number of bytes. Status code:
  717. X/*    the number of bytes actually read, or FAIL. A read of zero bytes
  718. X/*    normally indicates an end-of-file condition (see kwrite).
  719. X/*
  720. X/*    Kclose() sends a protocol abort sequence to the network partner.
  721. X/*    This function should be called to terminate the k protocol driver
  722. X/*    at the other end, or to confirm reception of a protocol abort sequence.
  723. X/*    Kclose always returns zero exit status.
  724. X/*
  725. X/*    The function kfail() is called by the strategy layer functions to 
  726. X/*    indicate protocol failure or termination.
  727. X/* FUNCTIONS AND MACROS
  728. X/*    kwproto, krproto, kclsproto
  729. X/* BUGS
  730. X/*    Zero byte read/writes are a clumsy way to handle end-of-files. 
  731. X/*    They have been implemented for the sake of compatibility with uucico.
  732. X/* AUTHOR(S)
  733. X/*    Wietse Venema
  734. X/*    Eindhoven University of Technology
  735. X/*    Department of Mathematics and Computer Science
  736. X/*    Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  737. X/* CREATION DATE
  738. X/*    Mon Feb  3 11:14:13 MET 1986
  739. X/* LAST MODIFICATION
  740. X/*    Mon Apr  4 23:43:28 MET 1988
  741. X/* VERSION/RELEASE
  742. X/*    1.3
  743. X/*--*/
  744. X
  745. X#ifdef unix
  746. X# ifdef    SIII
  747. X#   include <termio.h>
  748. X# else
  749. X#   include <sgtty.h>
  750. X# endif
  751. X#endif
  752. X#include <setjmp.h>
  753. X#include "kp.h"
  754. X
  755. Xstatic jmp_buf Failbuf;
  756. X
  757. Xkfail()
  758. X{
  759. X    longjmp(Failbuf,TRUE);
  760. X}
  761. X
  762. Xkopen(fd)
  763. Xint fd;
  764. X{
  765. X#ifdef unix
  766. X# ifdef SIII
  767. X    struct termio ttymode;
  768. X
  769. X    ioctl(fd,TCGETA,&ttymode);
  770. X    ttymode.c_iflag = IXOFF|IXON|ISTRIP;
  771. X    ttymode.c_cc[VMIN] = 1;
  772. X    ttymode.c_cc[VTIME] = 0;
  773. X    ioctl(fd,TCSETA,&ttymode);
  774. X# else
  775. X    struct sgttyb ttymode;
  776. X
  777. X    gtty(fd,&ttymode);
  778. X    ttymode.sg_flags |= (TANDEM|RAW);
  779. X    ttymode.sg_flags &= ~(ECHO|CBREAK);
  780. X    stty(fd,&ttymode);
  781. X# endif
  782. X#else
  783. X    xioctl(1);
  784. X#endif
  785. X    return 0;
  786. X}
  787. X
  788. Xkwrite(fd,buf,len)
  789. Xint fd;
  790. Xregister char *buf;
  791. Xregister int len;
  792. X{
  793. X    static char  packbuf[MAXPACKSIZ];
  794. X    static char *packptr = packbuf;
  795. X    register int c,i,rest,shift;
  796. X
  797. X    /* set error trap */
  798. X
  799. X    if (setjmp(Failbuf))
  800. X    return FAIL;
  801. X
  802. X    /* if 'end of data' send null packet */
  803. X
  804. X    if (len <= 0) {
  805. X    kwproto(fd,NULLP,0);
  806. X    return 0;
  807. X
  808. X    /* expand 3 eight-bit bytes to four six-bit bytes */
  809. X
  810. X    } else {
  811. X    for (rest = shift = i = 0; i < len; shift = (shift+STEP)%OUT,i++) {
  812. X
  813. X        c = *buf++ & 0377;                /* No sign extension */
  814. X        *packptr++ = tosix(rest|(c << shift));    /* Assemble byte */
  815. X        rest = (c >> (OUT-shift));            /* Save unused bits */
  816. X
  817. X        if (shift == (OUT-STEP)) {            /* At byte boundary? */
  818. X        *packptr++ = tosix(rest);        /* Make 'fourth' byte */
  819. X        rest = 0;                /* No unused bits now */
  820. X        if (packptr-packbuf > PACKSIZ-4) {    /* Check packet size */
  821. X            kwproto(fd,packbuf,packptr-packbuf);
  822. X            packptr = packbuf;
  823. X        }
  824. X        }
  825. X    }
  826. X    if (shift) {                    /* Any bits left? */
  827. X        *packptr++ = tosix(rest);            /* Put them there */
  828. X    }
  829. X    if (packptr > packbuf) {            /* Flush buffer */
  830. X        kwproto(fd,packbuf,packptr-packbuf);    /* Ship it off */
  831. X        packptr = packbuf;
  832. X    }
  833. X    return i;
  834. X    }
  835. X}
  836. X
  837. Xkread(fd,buf,len)
  838. Xint fd;
  839. Xchar *buf;
  840. Xint len;
  841. X{
  842. X    static char packbuf[MAXPACKSIZ] = "";
  843. X    static char *packptr = packbuf;
  844. X    static int  packsiz = 0;
  845. X    register int i,c;
  846. X    static int shift,rest;
  847. X
  848. X    /* set error trap */
  849. X
  850. X    if (setjmp(Failbuf))
  851. X    return FAIL;
  852. X
  853. X    /* read packet if buffer is empty */
  854. X
  855. X    if (packsiz <= 0) {
  856. X    krproto(fd,packptr = packbuf,&packsiz);
  857. X    rest = shift = 0;
  858. X    }
  859. X
  860. X    /* unpack (remainder of) buffer; return 0 if empty packet received */
  861. X
  862. X    for (i = 0; (i < len) && packsiz--; shift = (shift+STEP)%IN) 
  863. X    {
  864. X    c = unsix(*packptr++);
  865. X    if (shift)
  866. X        buf[i++] = (rest | (c << (IN-shift)));
  867. X    rest = (c >> shift);
  868. X    }
  869. X    return i;
  870. X}
  871. X
  872. Xkclose(fd)
  873. Xint fd;
  874. X{
  875. X    /* not here - pass job to the lower layer that understands packet types */
  876. X
  877. X    kclsproto(fd);
  878. X    return 0;
  879. X}
  880. X
  881. X
  882. END_OF_kpres.c
  883. if test 4951 -ne `wc -c <kpres.c`; then
  884.     echo shar: \"kpres.c\" unpacked with wrong size!
  885. fi
  886. # end of overwriting check
  887. fi
  888. if test -f logs.c -a "${1}" != "-c" ; then 
  889.   echo shar: Will not over-write existing file \"logs.c\"
  890. else
  891. echo shar: Extracting \"logs.c\" \(4714 characters\)
  892. sed "s/^X//" >logs.c <<'END_OF_logs.c'
  893. X/*++
  894. X/* NAME
  895. X/*      logs 3
  896. X/* SUMMARY
  897. X/*      error logging, status reports, debugging
  898. X/* PROJECT
  899. X/*      pc-mail
  900. X/* PACKAGE
  901. X/*      cico
  902. X/* SYNOPSIS
  903. X/*      void dbg(fmt[,args]);
  904. X/*      char *fmt;
  905. X/*
  906. X/*      int open_log();
  907. X/*
  908. X/*      void log(fmt[,args]);
  909. X/*      char *fmt;
  910. X/*
  911. X/*      void trap(code,fmt[,args]);
  912. X/*      char *fmt;
  913. X/* DESCRIPTION
  914. X/*      All functions in this module do some form of logging, and accept
  915. X/*      printf-like format strings with %s, %c, and %S, %C. The latter
  916. X/*    two cause output mapping of arbitrary byte values to printable codes.
  917. X/*
  918. X/*      dbg() formats its arguments and writes the result to the standard
  919. X/*      output.
  920. X/*
  921. X/*      open_log() tries to open the logfile for writing. It returns
  922. X/*      a status E_WRITERR if the file could not be opened or created.
  923. X/*
  924. X/*      log() writes status info to the log file. If debugging is enabled,
  925. X/*    the message is also written to the standard output.
  926. X/*
  927. X/*      trap() writes a message to the log file and performs a longjmp call
  928. X/*      (systrap) with the status as given in the code parameter. If 
  929. X/*    debugging is enabled, the message is also written to the standard 
  930. X/*    output.
  931. X/* FUNCTIONS AND MACROS
  932. X/*      longjmp()
  933. X/* FILES
  934. X/*      LOGFILE         status reports
  935. X/* BUGS
  936. X/*      Logfile info may be lost if the program terminates abnormally.
  937. X/*      We do not open/close the with each log() call since that would
  938. X/*      slow down performance on floppy-based systems dramatically.
  939. X/* AUTHOR(S)
  940. X/*      W.Z. Venema
  941. X/*      Eindhoven University of Technology
  942. X/*      Department of Mathematics and Computer Science
  943. X/*      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  944. X/* CREATION DATE
  945. X/*      Thu Mar 26 17:45:19 GMT+1:00 1987
  946. X/* LAST MODIFICATION
  947. X/*    Mon Apr  4 23:44:00 MET 1988
  948. X/* VERSION/RELEASE
  949. X/*    1.3
  950. X/*--*/
  951. X
  952. X#include <setjmp.h>
  953. X#include <ctype.h>
  954. X#include <varargs.h>
  955. X#include "defs.h"
  956. X#include "logs.h"
  957. X#include "path.h"
  958. X#include "status.h"
  959. X
  960. X#define    dbgout    stdout        /* where debugging output should go */
  961. X
  962. Xhidden FILE *logfp = NULL;    /* log file file pointer */
  963. Xhidden char *visible();        /* map characters to readable codes */
  964. Xhidden void dprintf();        /* special-purpose formatting function */
  965. X
  966. X/* dbg - write debugging info to the debugging output */
  967. X
  968. X/* VARARGS1 */
  969. X
  970. Xpublic void dbg(fmt,va_alist)
  971. Xregister char *fmt;
  972. Xva_dcl
  973. X{
  974. X    va_list s;
  975. X
  976. X    va_start(s);
  977. X    dprintf(dbgout,fmt,s);
  978. X    va_end(s);
  979. X}
  980. X
  981. X/* open_log - check the logfile can be written */
  982. X
  983. Xpublic int open_log()
  984. X{
  985. X    if (logfp == NULL && (logfp = fopen(logfile(),"a")) == NULL)
  986. X    return(E_WRITERR);
  987. X    else
  988. X    return(0);
  989. X}
  990. X
  991. X/* log - write status info to the log file */
  992. X
  993. X/* VARARGS1 */
  994. X
  995. Xpublic void log(fmt,va_alist)
  996. Xregister char *fmt;
  997. Xva_dcl
  998. X{
  999. X    va_list s;
  1000. X
  1001. X    /* log file should be open! */
  1002. X
  1003. X    if (logfp == NULL)
  1004. X    exit(E_CONFUSED);
  1005. X
  1006. X    /* write status record to log file */
  1007. X
  1008. X    va_start(s);
  1009. X    dprintf(logfp,fmt,s);
  1010. X    putc('\n',logfp);
  1011. X    va_end(s);
  1012. X
  1013. X    /* if debugging on, write also to debugging output */
  1014. X
  1015. X    if (dflag) {
  1016. X    va_start(s);
  1017. X    dprintf(dbgout,fmt,s);
  1018. X    putc('\n',dbgout);
  1019. X    va_end(s);
  1020. X   }
  1021. X}
  1022. X
  1023. X/* trap - exception handler */
  1024. X
  1025. X/* VARARGS2 */
  1026. X
  1027. Xpublic void trap(code,fmt,va_alist)
  1028. Xint code;
  1029. Xchar *fmt;
  1030. Xva_dcl
  1031. X{
  1032. X    va_list s;
  1033. X
  1034. X    /* write exception record to log file */
  1035. X
  1036. X    va_start(s);
  1037. X    dprintf(logfp,fmt,s);
  1038. X    putc('\n',logfp);
  1039. X    va_end(s);
  1040. X
  1041. X    /* if debugging on, write also to debugging output */
  1042. X
  1043. X    if (dflag) {
  1044. X    va_start(s);
  1045. X    dprintf(dbgout,fmt,s);
  1046. X    putc('\n',logfp);
  1047. X    va_end(s);
  1048. X    }
  1049. X    longjmp(systrap,code);
  1050. X}
  1051. X
  1052. X/* visible - turn arbitrary character into something visible */
  1053. X
  1054. Xstatic char *visible(c)
  1055. Xregister int c;
  1056. X{
  1057. X    static char buf[5];
  1058. X
  1059. X    switch(c&=0377) {
  1060. X    default:
  1061. X    sprintf(buf,isascii(c) && isprint(c) ? "%c" : "\\%03o",c);
  1062. X    return(buf);
  1063. X    case ' ':
  1064. X    return("\\s");
  1065. X    case '\b':
  1066. X    return("\\b");
  1067. X    case '\t':
  1068. X    return("\\t");
  1069. X    case '\r':
  1070. X    return("\\r");
  1071. X    case '\n':
  1072. X    return("\\n");
  1073. X    case '\f':
  1074. X    return("\\f");
  1075. X    case '\\':
  1076. X    return("\\\\");
  1077. X    }
  1078. X}
  1079. X
  1080. X/* dprintf - handle %s, %c, %S and %C format requests */
  1081. X
  1082. Xstatic void dprintf(fp,fmt,s)
  1083. Xregister FILE *fp;
  1084. Xregister char *fmt;
  1085. Xva_list s;
  1086. X{
  1087. X    register int c;
  1088. X
  1089. X    for (/* void */; c = *fmt; fmt++) {
  1090. X    if (c != '%') {
  1091. X        putc(c,fp);
  1092. X    } else if ((c = *++fmt) == 'S') {        /* %S: translated */
  1093. X        register char *cp = va_arg(s,char *);
  1094. X        while(*cp)
  1095. X        fputs(visible(*cp++&0377),fp);
  1096. X    } else if (c == 'C') {                /* %C: translated */
  1097. X        fputs(visible(va_arg(s,int)),fp);
  1098. X    } else if (c == 's') {                /* %s: string, as is */
  1099. X        fputs(va_arg(s,char *),fp);
  1100. X    } else if (c == 'c') {                /* %c: char, as is */
  1101. X        putc(va_arg(s,int),fp);
  1102. X    } else if (c == '%') {                /* real % character */
  1103. X        putc(c,fp);
  1104. X    }
  1105. X    }
  1106. X}
  1107. END_OF_logs.c
  1108. if test 4714 -ne `wc -c <logs.c`; then
  1109.     echo shar: \"logs.c\" unpacked with wrong size!
  1110. fi
  1111. # end of overwriting check
  1112. fi
  1113. if test -f path.h -a "${1}" != "-c" ; then 
  1114.   echo shar: Will not over-write existing file \"path.h\"
  1115. else
  1116. echo shar: Extracting \"path.h\" \(4342 characters\)
  1117. sed "s/^X//" >path.h <<'END_OF_path.h'
  1118. X/*++
  1119. X/* NAME
  1120. X/*    path
  1121. X/* SUMMARY
  1122. X/*    system-dependent file name definitions
  1123. X/* PROJECT
  1124. X/*    pc-mail
  1125. X/* PACKAGE
  1126. X/*    general
  1127. X/* SYNOPSIS
  1128. X/*    #include "path.h"
  1129. X/* DESCRIPTION
  1130. X/*    File-system dependent definitions should be changed here.
  1131. X/* .nf
  1132. X
  1133. X/* /* the minmal number of open files we think we need */
  1134. X
  1135. X#define    MINFILES    10
  1136. X
  1137. X/* /*    system-dependent defaults */
  1138. X
  1139. X#ifdef    unix
  1140. X#define    THISDIR        "."        /* current directory */
  1141. X#define    DEFSPOOL    "./spool"    /* default spool directory */
  1142. X#define    DEFEDIT        "vi"        /* default editor */
  1143. X#ifdef SIII
  1144. X#define    DEFPRINT    "lp"        /* printer spooler */
  1145. X#else
  1146. X#define    DEFPRINT    "lpr"        /* printer spooler */
  1147. X#endif
  1148. X#define    MAILFILE    "mail.msg"    /* temporary message file */
  1149. X#define    TMPALIAS    "tmp.alias"    /* temp alias file */
  1150. X#define    NULLDEV        "/dev/null"    /* bit dump */
  1151. X#endif
  1152. X
  1153. X#ifdef    MSDOS
  1154. X#define    THISDIR        "."        /* current directory */
  1155. X#define    DEFSPOOL    "\\spool"    /* spool directory */
  1156. X#define    DEFEDIT        "edlin"        /* default editor */
  1157. X#define DEFPRINT    "PRN"        /* default printer */
  1158. X#define    MAILFILE    "mail.msg"    /* temp message file */
  1159. X#define    TMPALIAS    "alias.tmp"    /* temp alias file */
  1160. X#define    NULLDEV        "NUL"        /* bit dump */
  1161. X#endif
  1162. X
  1163. X/* /* system-dependent function calls for file & printer access */
  1164. X
  1165. X#ifdef unix
  1166. X#define    propen()    popen(mailprn,"w")    /* open printe stream */
  1167. X#define    prclose(p)    pclose(p)        /* close print stream */
  1168. X#define    fspool(file)    strcons("%s/%s",maildir,file)
  1169. X#endif
  1170. X
  1171. X#ifdef MSDOS
  1172. X#define    propen()    fopen(mailprn,"a")    /* open print stream */
  1173. X#define    prclose(p)    (putc('\014',p),fclose(p)) /* close print stream */
  1174. X#define    fspool(file)    strcons("%s\\%s",maildir,file)
  1175. X#endif
  1176. X
  1177. X/* /* system-independent file names */
  1178. X
  1179. X#define    SMAIL    "smail"            /* queues a mail message */
  1180. X#define    CICO    "cico"            /* file transfer program */
  1181. X#define    RMAIL    "rmail"            /* extract originator address */
  1182. X
  1183. X/* /*
  1184. X* The spool directory is used for storage of all files manipulated
  1185. X* by the mail programs. Message files should always have a meta file
  1186. X* with information about the destination or origin of a message file.
  1187. X*
  1188. X* Message/meta file names are of the form <letter><sequence number>.
  1189. X* Corresponding message/meta files have the same sequene number.
  1190. X* The following definitions are for the <letter> part of spool files.
  1191. X*/
  1192. X
  1193. X#define    LOGFILE    "LOGFILE"        /* transaction logs */
  1194. X
  1195. X#define    NEWPFX    "n"            /* received message */
  1196. X#define    HDRPFX    "h"            /* originator of new mail */
  1197. X#define    OLDPFX    "o"            /* originator of old mail */
  1198. X
  1199. X#define    MSGPFX    "d"            /* message ready to be sent */
  1200. X#define    XQTPFX    "x"            /* its destination */
  1201. X
  1202. X#define    EDTPFX    "e"            /* message being worked on */
  1203. X#define    COMPFX    "c"            /* its description */
  1204. X
  1205. X#define    SETPFX    "s"            /* system parameter file */
  1206. X
  1207. X#define    ALIPFX    "a"            /* alias data base */
  1208. X
  1209. X#define    SPLFMT    "%s%05d"        /* spool-file name format */
  1210. X
  1211. X/* /* 
  1212. X* The following macros provide convenient access of spool files, so we
  1213. X* don't have to remember the spool file name format and prefix stuff.
  1214. X*/
  1215. X
  1216. X#define    sendmail(file,to)    spoolfil(file,to,MSGPFX,XQTPFX)
  1217. X#define    workon(fname,meta)    spoolfil(fname,meta,EDTPFX,COMPFX)
  1218. X
  1219. X#define    parm_file()        fspool(strcons(SPLFMT,SETPFX,0))
  1220. X#define    aliases()        fspool(strcons(SPLFMT,ALIPFX,0))
  1221. X#define logfile()        fspool(LOGFILE)
  1222. X
  1223. X#define meta_file(type,id)    fspool(strcons(SPLFMT,type,id))
  1224. X#define mesg_file(type,id)    fspool(strcons(SPLFMT,type,id))
  1225. X
  1226. X#define    work_meta(id)        fspool(strcons(SPLFMT,COMPFX,id))
  1227. X#define    work_mesg(id)        fspool(strcons(SPLFMT,EDTPFX,id))
  1228. X
  1229. X#define    in_mesg(id)        fspool(strcons(SPLFMT,NEWPFX,id))
  1230. X#define    in_meta(id)        fspool(strcons(SPLFMT,OLDPFX,id))
  1231. X
  1232. X#define    new_mesg(id)        fspool(strcons(SPLFMT,NEWPFX,id))
  1233. X#define    new_meta(id)        fspool(strcons(SPLFMT,HDRPFX,id))
  1234. X
  1235. X#define    out_mesg(id)        fspool(strcons(SPLFMT,MSGPFX,id))
  1236. X#define out_meta(id)        fspool(strcons(SPLFMT,XQTPFX,id))
  1237. X
  1238. X/* /* stuff taken from the environment */
  1239. X
  1240. Xextern char *editor;        /* path to editor */
  1241. Xextern char *maildir;        /* spool directory */
  1242. Xextern char *mailprn;        /* how to print */
  1243. Xextern char *mailcmd;        /* do this on exit */
  1244. X
  1245. Xextern int pathinit();        /* get path info from environment */
  1246. X/* AUTHOR(S)
  1247. X/*    W.Z. Venema
  1248. X/*    Eindhoven University of Technology
  1249. X/*    Department of Mathematics and Computer Science
  1250. X/*    Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  1251. X/* CREATION DATE
  1252. X/*    Sun Apr  5 13:23:45 GMT+1:00 1987
  1253. X/* LAST MODIFICATION
  1254. X/*    Wed Apr  6 00:21:29 MET 1988
  1255. X/* VERSION/RELEASE
  1256. X/*    1.4
  1257. X/*--*/
  1258. END_OF_path.h
  1259. if test 4342 -ne `wc -c <path.h`; then
  1260.     echo shar: \"path.h\" unpacked with wrong size!
  1261. fi
  1262. # end of overwriting check
  1263. fi
  1264. if test -f sendwork.c -a "${1}" != "-c" ; then 
  1265.   echo shar: Will not over-write existing file \"sendwork.c\"
  1266. else
  1267. echo shar: Extracting \"sendwork.c\" \(4326 characters\)
  1268. sed "s/^X//" >sendwork.c <<'END_OF_sendwork.c'
  1269. X/*++
  1270. X/* NAME
  1271. X/*      sendwork 3
  1272. X/* SUMMARY
  1273. X/*      send local work to remote system
  1274. X/* PROJECT
  1275. X/*      pc-mail
  1276. X/* PACKAGE
  1277. X/*      cico
  1278. X/* SYNOPSIS
  1279. X/*      #include "work.h"
  1280. X/*
  1281. X/*      void sendwork(wrk)
  1282. X/*      work *wrk;
  1283. X/* DESCRIPTION
  1284. X/*      sendwork converts names and contents of local work files,
  1285. X/*    sends them to the remote system and deletes the files after 
  1286. X/*    successfull transfer.
  1287. X/*
  1288. X/*    In particular, it generates appropriate "From " lines at the
  1289. X/*    beginning of an outgoing mail message.
  1290. X/* FUNCTIONS AND MACROS
  1291. X/*      rmtname()
  1292. X/* SEE ALSO
  1293. X/*      scanwork(3)     locates work in the spool directory
  1294. X/*      rmtname(3)      rules for remote file name construction
  1295. X/* DIAGNOSTICS
  1296. X/*    sendwork() returns via longjmp(systrap,errorcode) in case
  1297. X/*    of unrecoverable problems.
  1298. X/*
  1299. X/*    The error codes are: E_CONFUSED (unexpected work type),
  1300. X/*    E_LOST (timed out), E_READERR (file read error).
  1301. X/* AUTHOR(S)
  1302. X/*      W.Z. Venema
  1303. X/*      Eindhoven University of Technology
  1304. X/*      Department of Mathematics and Computer Science
  1305. X/*      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  1306. X/* CREATION DATE
  1307. X/*      Thu Mar 26 11:32:23 GMT+1:00 1987
  1308. X/* LAST MODIFICATION
  1309. X/*    Wed Apr  6 00:22:23 MET 1988
  1310. X/* VERSION/RELEASE
  1311. X/*    1.4
  1312. X/*--*/
  1313. X
  1314. X#include <time.h>
  1315. X#include "defs.h"
  1316. X#include "work.h"
  1317. X#include "logs.h"
  1318. X#include "status.h"
  1319. X#include "params.h"
  1320. X#include "comm.h"
  1321. X
  1322. Xextern struct tm *localtime();            /* std C library */
  1323. X
  1324. X/*
  1325. X* A pc-mail system can connect to the UNIX net in at least two modes:
  1326. X*
  1327. X* 1. As a real UUCP node, with it's own node name. This node name will
  1328. X* have to appear in the "From " lines of outgoing mail. A consequence 
  1329. X* is that the pc mail node name should be known in mailer routing tables.
  1330. X* Obviously this implies some administrative work when a pc mail node 
  1331. X* is added to the net or taken out of operation. 
  1332. X*
  1333. X* 2. As an ordinary user. The program lets the UNIX host believe that
  1334. X* mail messages come from an ordinary user. Recipients of mail will
  1335. X* not be able to see that the mail came from the pc. Only the UNIX host 
  1336. X* knows it should forward mail for unixhost!xyz to the pc-mail node.
  1337. X* This approach has the advantage that adding/deleting pc-mail nodes 
  1338. X* is simpler.
  1339. X*/
  1340. X
  1341. X#ifdef    UUCP_NODE                /* case 1 */
  1342. X#   define U_USER    "root"            /* use current user's name */
  1343. X#   define U_HOST    LOGIN_NAME        /* use pc host name */
  1344. X#else                        /* case 2 */
  1345. X#   define U_USER    LOGIN_NAME        /* use remote login name */
  1346. X#   define U_HOST    rmthost            /* use remote host name */
  1347. X#endif
  1348. X
  1349. X/* sendwork - adapt file contents for remote host */
  1350. X
  1351. Xpublic sendwork(wrk)
  1352. Xwork *wrk;
  1353. X{
  1354. X    register char *date;
  1355. X    long secs;
  1356. X
  1357. X    switch (wrk->type) {
  1358. X
  1359. X    /* 
  1360. X    * Local D files contain the mail message, nothing more, nothing less.
  1361. X    * We add a "From " line with originator/date/system.
  1362. X    * Otherwise, D files can be sent as is.
  1363. X    */
  1364. X
  1365. X    case 'D':
  1366. X    secs = time((long *)0);
  1367. X    (date = asctime(localtime(&secs)))[24] = '\0';
  1368. X    say(strcons("From %s %s remote from %s\n",U_USER,date,U_HOST));
  1369. X    send_file(wrk->fp);
  1370. X    break;
  1371. X
  1372. X    /* 
  1373. X    * Local X files contain the destination network address only.
  1374. X    * Therefore we must mock up some extra info to make the 
  1375. X    * remote uuxqt program happy.
  1376. X    */
  1377. X
  1378. X    case 'X':
  1379. X    say(strcons("U %s %s\n",U_USER,U_HOST));    /* U user system */
  1380. X    say(strcons("F %s\n",rmtname('D',wrk->tail)));    /* F D.rmtsysGnumber */
  1381. X    say(strcons("I %s\n",rmtname('D',wrk->tail)));    /* I D.rmtsysGnumber */
  1382. X    say("C rmail ");                /* C rmail */
  1383. X    send_file(wrk->fp);                /* send destination */
  1384. X    break;
  1385. X
  1386. X    default:
  1387. X    trap(E_CONFUSED,"INTERNAL ERROR (unexpected work type: %c)",wrk->type);
  1388. X    }
  1389. X}
  1390. X
  1391. X/* say - write string to host */
  1392. X
  1393. Xhidden say(str)
  1394. Xchar *str;
  1395. X{
  1396. X    if (CALL(Write)(ttfd,str,strlen(str)) < 0)
  1397. X    trap(E_LOST,"FAILED (link lost)");
  1398. X}
  1399. X
  1400. X/* send_file - do the nitty-gritty of file transfer; traps on all errors */
  1401. X
  1402. Xhidden send_file(fp)
  1403. Xregister FILE *fp;
  1404. X{
  1405. X    register int nread,nwrite = 0;
  1406. X    char buf[BUFSIZ];
  1407. X    register int rerror;
  1408. X
  1409. X    while ((nread = fread(buf,sizeof(*buf),sizeof(buf),fp)) > 0 &&
  1410. X    (nwrite = CALL(Write)(ttfd,buf,nread)) == nread)
  1411. X    /* empty */;
  1412. X    rerror = ferror(fp);
  1413. X    fclose(fp);
  1414. X
  1415. X    if (rerror) {
  1416. X    trap(E_READERR,"FILE READ ERROR (%s)",sys_errlist[errno]);
  1417. X    /* NOTREACHED */
  1418. X    } else if (nwrite < 0 || CALL(Write)(ttfd,buf,0) != 0) {
  1419. X    trap(E_LOST,"FAILED (link lost)");
  1420. X    /* NOTREACHED */
  1421. X    }
  1422. X}
  1423. END_OF_sendwork.c
  1424. if test 4326 -ne `wc -c <sendwork.c`; then
  1425.     echo shar: \"sendwork.c\" unpacked with wrong size!
  1426. fi
  1427. # end of overwriting check
  1428. fi
  1429. if test -f spoolfil.c -a "${1}" != "-c" ; then 
  1430.   echo shar: Will not over-write existing file \"spoolfil.c\"
  1431. else
  1432. echo shar: Extracting \"spoolfil.c\" \(4020 characters\)
  1433. sed "s/^X//" >spoolfil.c <<'END_OF_spoolfil.c'
  1434. X/*++
  1435. X/* NAME
  1436. X/*    spoolfil,metafile 3
  1437. X/* SUMMARY
  1438. X/*    create message file and meta file
  1439. X/* PROJECT
  1440. X/*    pc-mail
  1441. X/* PACKAGE
  1442. X/*    general utilities
  1443. X/* SYNOPSIS
  1444. X/*    int spoolfil(mesg,meta_info,mesg_prefix,meta_prefix)
  1445. X/*    char *mesg;
  1446. X/*    char *meta_info;
  1447. X/*    char *mesg_prefix;
  1448. X/*    char *meta_prefix;
  1449. X/*
  1450. X/*    int metafile(string,path)
  1451. X/*    char *string;
  1452. X/*    char *path;
  1453. X/* DESCRIPTION
  1454. X/*    spoolfil() creates a message, meta file pair in the spool
  1455. X/*    directory. 
  1456. X/*
  1457. X/*    "mesg" should be null-terminated string with the name of an existing 
  1458. X/*    file. The contents of that file are filtered to produce a
  1459. X/*    clean ASCII file.
  1460. X/*
  1461. X/*    "meta-info" is a string with additional information that is 
  1462. X/*    written to a meta file (usually name of mail recipient, mail
  1463. X/*    originator or a comment describing the contents of the message file).
  1464. X/*
  1465. X/*    "mesg_prefix," "meta_prefix" are strings that will be used for building
  1466. X/*    names for files in the spool directory.
  1467. X/*
  1468. X/*    metafile() creates a file, writes a string to it and terminates
  1469. X/*    the file with a newline character. This function is typically used
  1470. X/*    to create a file with meta information (mail originator, message
  1471. X/*    summary etc.).
  1472. X/* FUNCTIONS AND MACROS
  1473. X/*    ascopen(), ascget(), ascclose(), newseqno()
  1474. X/* DIAGNOSTICS
  1475. X/*    A nonzero return value indicates an error condition (see status.h)
  1476. X/* SEE ALSO
  1477. X/*    status(5)    return values
  1478. X/*    ascf(3)        ASCII filter
  1479. X/* BUGS
  1480. X/*    Wordprocessor control codes etc will be lost when spoolfil copies 
  1481. X/*    a file.
  1482. X/* AUTHOR(S)
  1483. X/*    W.Z. Venema
  1484. X/*    Eindhoven University of Technology
  1485. X/*    Department of Mathematics and Computer Science
  1486. X/*    Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  1487. X/* CREATION DATE
  1488. X/*    Mon May 18 18:45:10 GMT+1:00 1987
  1489. X/* LAST MODIFICATION
  1490. X/*    Mon Apr  4 23:50:14 MET 1988
  1491. X/* VERSION/RELEASE
  1492. X/*    1.3
  1493. X/*--*/
  1494. X
  1495. X#include "defs.h"
  1496. X#include "path.h"
  1497. X#include "ascf.h"
  1498. X#include "status.h"
  1499. X
  1500. X/* metafile - create a one-liner file */
  1501. X
  1502. Xpublic int metafile(string,file)
  1503. Xchar *string;
  1504. Xchar *file;
  1505. X{
  1506. X    register FILE *fp;
  1507. X
  1508. X    if ((fp = fopen(file,"w")) == 0) {
  1509. X    return(E_WRITERR);
  1510. X    } else if (fprintf(fp,"%s\n",string),ferror(fp)) {
  1511. X    fclose(fp);
  1512. X    return(E_WRITERR);
  1513. X    } else {
  1514. X    fclose(fp);
  1515. X    return(0);
  1516. X    }
  1517. X}
  1518. X    
  1519. X/* spoolfil - make arbitrary spool file */
  1520. X
  1521. Xpublic int spoolfil(fname,meta,msgpfx,auxpfx)
  1522. Xchar *fname;
  1523. Xchar *meta;
  1524. Xchar *msgpfx;
  1525. Xchar *auxpfx;
  1526. X{
  1527. X    register int newid = newseqno();            /* new message id */
  1528. X    register int stat;                    /* some status */
  1529. X    char *msgpath;                    /* new message file */
  1530. X    char *auxpath;                    /* new meta file */
  1531. X
  1532. X    msgpath = mesg_file(msgpfx,newid);            /* message file path */
  1533. X    auxpath = meta_file(auxpfx,newid);            /* meta file path */
  1534. X
  1535. X    /* copy disk file to spool file, check for errors */
  1536. X
  1537. X    if (stat = copyfile(fname,msgpath)) {        /* read/write error */
  1538. X    unlink(msgpath);                /* delete msg file */
  1539. X    return(stat);                    /* notify caller */
  1540. X
  1541. X    /* create file for meta information, check for errors */
  1542. X
  1543. X    } else if (stat = metafile(meta,auxpath)) {        /* metafile error */
  1544. X    unlink(msgpath);                /* delete msg file */
  1545. X    unlink(auxpath);                /* delete meta file */
  1546. X    return(stat);                    /* notify caller */
  1547. X
  1548. X    /* when nothing went wrong */
  1549. X
  1550. X    } else {
  1551. X    chmod(msgpath,0444);                /* message read-only */
  1552. X    chmod(auxpath,0444);                /* metafile read-only */
  1553. X    return(0);                    /* own error handling */
  1554. X    }
  1555. X}
  1556. X
  1557. X/* copyfile - copy a file and filter it */
  1558. X
  1559. Xpublic int copyfile(from,to)
  1560. Xchar *from;
  1561. Xchar *to;
  1562. X{
  1563. X    register FILE *in,*out;            /* file pointers */
  1564. X    int rerr,werr;                /* error status */
  1565. X
  1566. X    if ((in = ascopen(from,"r")) == 0) {    /* cannot read ?? */
  1567. X    return(E_READERR);
  1568. X    } else if ((out = fopen(to,"w")) == 0) {    /* cannot write */
  1569. X    ascclose(in);
  1570. X    return(E_WRITERR);
  1571. X    } else {
  1572. X    register int c;
  1573. X    while ((c = ascget(in)) != EOF)        /* ASCII filter */
  1574. X       putc(c,out);
  1575. X    rerr = ferror(in);            /* check read status */
  1576. X    werr = ferror(out);            /* check write status */
  1577. X    ascclose(in);
  1578. X    fclose(out);
  1579. X    if (rerr) {
  1580. X        return(E_READERR);
  1581. X    } else if (werr) {
  1582. X        return(E_WRITERR);
  1583. X    } else {
  1584. X        return(0);
  1585. X    }
  1586. X    }
  1587. X}
  1588. END_OF_spoolfil.c
  1589. if test 4020 -ne `wc -c <spoolfil.c`; then
  1590.     echo shar: \"spoolfil.c\" unpacked with wrong size!
  1591. fi
  1592. # end of overwriting check
  1593. fi
  1594. if test -f srctoman.sh -a "${1}" != "-c" ; then 
  1595.   echo shar: Will not over-write existing file \"srctoman.sh\"
  1596. else
  1597. echo shar: Extracting \"srctoman.sh\" \(4444 characters\)
  1598. sed "s/^X//" >srctoman.sh <<'END_OF_srctoman.sh'
  1599. X: srctoman - see comment below
  1600. X
  1601. X: process arguments
  1602. X
  1603. Xwhile :
  1604. Xdo
  1605. X    case $1 in
  1606. X [0-9]) SECT=$1;;
  1607. X     -) LANG=$1; B='[#:]';;
  1608. X  -awk) LANG=$1; B='#';;
  1609. X    -c) LANG=$1; B='\/\*';;
  1610. X    -f) LANG=$1; B='[Cc]';;
  1611. X   -mk) LANG=$1; B='#';;
  1612. X -n|-t) LANG=$1; B='\\"';;
  1613. X    -p) LANG=$1; B='{';;
  1614. X    -r) LANG=$1; B='#';;
  1615. X    -C) LANG=$1; B=$2; shift;;
  1616. X    -*) ERROR="unknown option: $1"; break;;
  1617. X    "") ERROR="missing file argument"; break;;
  1618. X     *) break;;
  1619. X    esac
  1620. X    shift
  1621. Xdone
  1622. X
  1623. X: check error status
  1624. X
  1625. Xcase $ERROR in
  1626. X"") ;;
  1627. X *) echo "$0: $ERROR" 1>&2
  1628. X    echo "usage: $0 [-|-awk|-c|-f|-mk|-n|-p|-t|-r] [section] file(s)" 1>&2; exit 1;;
  1629. Xesac
  1630. X
  1631. X: set up for file suffix processing
  1632. X
  1633. Xcase $LANG in
  1634. X"") sh='[:#]';    r='#';    rh=$r;    awk='#'; mk='#';
  1635. X    c='\/\*';    h=$c;    y=$c;    l=$c;
  1636. X    f='[Cc]';    fh=$f;    p='{';    ph=$p;
  1637. X    ms='\\"';    nr=$ms;    mn=$ms;    man=$ms;
  1638. Xesac
  1639. X
  1640. X: extract comments
  1641. X
  1642. Xfor i in $*
  1643. Xdo
  1644. X    case $LANG in
  1645. X    "") eval B\="\$`expr $i : '^.*\.\([^.]*\)$'`"
  1646. X    test "$B" || { echo "$0: unknown suffix: $i; assuming c" 1>&2; B=$c; }
  1647. X    esac
  1648. X    sed '
  1649. X    /^'"$B"'++/,/^'"$B"'--/!d
  1650. X    /^'"$B"'++/d
  1651. X    /^'"$B"'--/d
  1652. X    s/[     ]*$//
  1653. X    /^'"$B"' \([A-Z]\)/{
  1654. X    s//\1/
  1655. X    /^NAME/{
  1656. X        N
  1657. X        s/^.*\n'"$B"'[     ]*//
  1658. X        h
  1659. X        y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/
  1660. X        s/^.*$/.TH & '"$SECT"'\
  1661. X.ad\
  1662. X.fi\
  1663. X.SH NAME/
  1664. X        p
  1665. X        g
  1666. X        s/ [0-9]$//
  1667. X        a\
  1668. X\\-
  1669. X        p
  1670. X        d
  1671. X    }
  1672. X    /^SUMMARY/d
  1673. X    /^DESCRIPTION/s//.SH &\
  1674. X.ad\
  1675. X.fi/
  1676. X    /^BUGS/s//.SH &\
  1677. X.ad\
  1678. X.fi/
  1679. X    /^DIAGNOSTICS/s//.SH &\
  1680. X.ad\
  1681. X.fi/
  1682. X    /^[A-Z][A-Z][A-Z][^a-z]*$/s//.SH &\
  1683. X.na\
  1684. X.nf/
  1685. X    p
  1686. X    d
  1687. X    }
  1688. X    s/^'"$B"'[     ]*//
  1689. X    s/^[     ]*$//
  1690. X' $i
  1691. Xdone 
  1692. X
  1693. Xexit
  1694. X
  1695. X:++
  1696. X: NAME
  1697. X:    srctoman 1
  1698. X: SUMMARY
  1699. X:    extract manual page from source file comment
  1700. X: PACKAGE
  1701. X:    source file maintentance tools
  1702. X: SYNOPSIS
  1703. X:    srctoman [-|-awk|-c|-f|-mk|-m|-n|-p|-t|-r] [section] file(s)
  1704. X: DESCRIPTION
  1705. X:    Srctoman converts comments in various programming languages to
  1706. X:    UNIX-style manual pages.
  1707. X:    The command processes comments in the style of newsource(1);
  1708. X:    its standard output is suitable for formatting with nroff(1) or 
  1709. X:    troff(1) using the "-man" macro package.  
  1710. X:    Typically, srctoman is integrated with make(1) scripts.
  1711. X:
  1712. X:    Source files are processed in the indicated order; if no
  1713. X:    files argument the command produces no output.
  1714. X:
  1715. X:    The source file language can be specified through a command-line
  1716. X:    option, or can be implied by the filename suffix.
  1717. X:    The expected start-of-comment symbol is shown in the last column.
  1718. X:
  1719. X: .nf
  1720. X    option    language    comment
  1721. X
  1722. X    -    shell        [:#]
  1723. X    -awk    awk        #
  1724. X    -c    c        /*
  1725. X    -f    fortran        [Cc]
  1726. X    -mk    make        #
  1727. X    -n    nroff        \\"
  1728. X    -p    pascal        {
  1729. X    -t    troff        \\"
  1730. X    -r    ratfor        #
  1731. X    -C    any language    next argument
  1732. X: .fi
  1733. X:
  1734. X: .nf
  1735. X    suffix    language    comment
  1736. X
  1737. X    .awk    awk        #
  1738. X    .c    c        /*
  1739. X    .f    fortran        [Cc]
  1740. X    .fh    fortran        [Cc]
  1741. X    .h    c        /*
  1742. X    .l    lex        /*
  1743. X    .man    nroff,troff    \\"
  1744. X    .mk    make        #
  1745. X    .me    nroff,troff    \\"
  1746. X    .ms    nroff,troff    \\"
  1747. X    .nr    nroff,troff    \\"
  1748. X    .p    pascal        {
  1749. X    .ph    pascal        {
  1750. X    .r    ratfor        #
  1751. X    .rh    ratfor        #
  1752. X    .sh    shell        [:#]
  1753. X    .y    yacc        /*
  1754. X: .fi
  1755. X:
  1756. X:    The required format of comments is discussed below, where SOC
  1757. X:    stands for the start-of-comment symbol of the language being used.
  1758. X:
  1759. X:    1) Start of manual: SOC, followed by `++'.
  1760. X:
  1761. X:    2) Section heading: SOC, blank, section name in upper case.
  1762. X:
  1763. X:    3) New paragraph: empty line or line with SOC only.
  1764. X:
  1765. X:    4) All other text: SOC and subsequent blanks or tabs are removed.
  1766. X:    Lines that do not start with SOC are left unchanged (useful for 
  1767. X:    inclusion of program text).
  1768. X:
  1769. X:    5) End of manual: SOC, followed by `--'.
  1770. X:    An end-of-comment may follow if the source file language requires this.
  1771. X:
  1772. X:    The following manual sections receive a special treatment:
  1773. X:    NAME and SUMMARY should appear at the beginning and in
  1774. X:    this order; DESCRIPTION, DIAGNOSTICS and BUGS will be
  1775. X:    right-margin adjusted.
  1776. X:    Other sections may be added freely without confusing srctoman.
  1777. X: COMMANDS
  1778. X:    sh(1), sed(1), expr(1)
  1779. X: SEE ALSO
  1780. X:    newsource(1), modsource(1), xman(1)
  1781. X:    The earlier commands new(1), mod(1), mkman(1) and dssman(1)
  1782. X:    by Ruud Zwart and Ben Noordzij (Erasmus University, Rotterdam) 
  1783. X: DIAGNOSTICS
  1784. X:    The program complains if an unknown language is specified
  1785. X:    or if the language cannot be deduced from the file suffix.
  1786. X: AUTHOR(S)
  1787. X:    W.Z. Venema
  1788. X:    Eindhoven University of Technology
  1789. X:    Department of Mathematics and Computer Science
  1790. X:    Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  1791. X: CREATION DATE
  1792. X:    Fri Jan 17 22:59:27 MET 1986
  1793. X: LAST MODIFICATION
  1794. X:    Thu Mar 10 20:08:15 MET 1988
  1795. X: VERSION/RELEASE
  1796. X:    1.20
  1797. X:--
  1798. X
  1799. X
  1800. END_OF_srctoman.sh
  1801. if test 4444 -ne `wc -c <srctoman.sh`; then
  1802.     echo shar: \"srctoman.sh\" unpacked with wrong size!
  1803. fi
  1804. chmod +x srctoman.sh
  1805. # end of overwriting check
  1806. fi
  1807. if test -f switcher.c -a "${1}" != "-c" ; then 
  1808.   echo shar: Will not over-write existing file \"switcher.c\"
  1809. else
  1810. echo shar: Extracting \"switcher.c\" \(4041 characters\)
  1811. sed "s/^X//" >switcher.c <<'END_OF_switcher.c'
  1812. X/*++
  1813. X/* NAME
  1814. X/*      switcher 3
  1815. X/* SUMMARY
  1816. X/*      master/slave protocol control switcher
  1817. X/* PROJECT
  1818. X/*      pc-mail
  1819. X/* PACKAGE
  1820. X/*      cico
  1821. X/* SYNOPSIS
  1822. X/*      int switcher(role)
  1823. X/*      int role;
  1824. X/* DESCRIPTION
  1825. X/*      switcher() takes care of the high-level protocol on top of
  1826. X/*      the packet protocol. 
  1827. X/*
  1828. X/*    The system is in one of two roles: MASTER or SLAVE. In MASTER
  1829. X/*    mode (initial mode of the caller) a system scans its local
  1830. X/*    spool directory for work until no more is found, and then
  1831. X/*    sends a H (hangup) request. The slave will respond with HY
  1832. X/*    if it has no work, otherwise it will respond with HN and
  1833. X/*    the two systems switch roles.
  1834. X/*
  1835. X/*    Work can be of the form of S (send) requests or R (receive)
  1836. X/*    requests. The slave responds with SY (RY) or SN (RN), depending on
  1837. X/*    whether it is willing to process the request. The recipient
  1838. X/*    of a message sends a CY or CN message, depending on whether
  1839. X/*    transmission was successfull.
  1840. X/*
  1841. X/*      Only H(angup) and S(end) requests are implemented here. This is
  1842. X/*      for security reasons. Thus, the only way to exchange data is
  1843. X/*      through electronic mail.
  1844. X/* FUNCTIONS AND MACROS
  1845. X/*      isok, talk(), hear(), trap(), scanwork(), sendwork()
  1846. X/*      rmtwork(), getwork()
  1847. X/* DIAGNOSTICS
  1848. X/*      Various nonzero status codes are returned in case of problems.
  1849. X/* AUTHOR(S)
  1850. X/*      W.Z. Venema
  1851. X/*      Eindhoven University of Technology
  1852. X/*      Department of Mathematics and Computer Science
  1853. X/*      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  1854. X/* CREATION DATE
  1855. X/*      Fri Mar 27 21:49:16 GMT+1:00 1987
  1856. X/* LAST MODIFICATION
  1857. X/*    Wed Apr  6 00:23:14 MET 1988
  1858. X/* VERSION/RELEASE
  1859. X/*    1.4
  1860. X/*--*/
  1861. X
  1862. X#include <setjmp.h>
  1863. X#include "defs.h"
  1864. X#include "work.h"
  1865. X#include "params.h"
  1866. X#include "comm.h"
  1867. X#include "logs.h"
  1868. X#include "status.h"
  1869. X
  1870. X/* switcher - handles master/slave role swicthing until all work is done */
  1871. X
  1872. Xpublic switcher(role)
  1873. Xregister int role;
  1874. X{
  1875. X    int *savetrap = systrap;
  1876. X    jmp_buf mytrap;
  1877. X    int status;
  1878. X
  1879. X    if (status = setjmp(systrap = mytrap)) {
  1880. X    systrap = savetrap;             /* get here on fatal errors */
  1881. X    return(status);
  1882. X    }
  1883. X
  1884. X    /* switch roles until both ends out of work */
  1885. X
  1886. X    while (role != DONE) {
  1887. X    switch (role) {
  1888. X    case MASTER:
  1889. X        role = master();
  1890. X        break;
  1891. X    case SLAVE:
  1892. X        role = slave();
  1893. X        break;
  1894. X    default:
  1895. X        trap(E_CONFUSED,"INTERNAL ERROR (unexpected role: %d)",role);
  1896. X    }
  1897. X    }
  1898. X    systrap = savetrap;                 /* get here if no fatal errors */
  1899. X    return(0);
  1900. X}
  1901. X
  1902. X/* master - process local work; when done, switch roles or finish */
  1903. X
  1904. Xhidden int master()
  1905. X{
  1906. X    register work *wrk;
  1907. X    register char *resp;
  1908. X
  1909. X    while (wrk = scanwork()) {                /* scan for work */
  1910. X    log("REQUEST (%s)",wrk->rqst);
  1911. X    if (wrk->fp == 0) {                /* check file exists */
  1912. X        log("CAN'T READ DATA (%s)",sys_errlist[errno]);
  1913. X    } else if (isok(wrk->rqst) == NO) {        /* check xfer allowed */
  1914. X        log("PERMISSION (DENIED)");
  1915. X    } else {                    /* adapt + send data */
  1916. X        sendwork(wrk);
  1917. X        log("REQUESTED (%s)",resp = hear());
  1918. X        if (strcmp(resp,"CY"))            /* check sucessfull */
  1919. X        trap(E_REJECT,"FAILED");        /* completion */
  1920. X        chmod(wrk->path,0666);            /* delete workfile */
  1921. X        unlink(wrk->path);                /* only if all well */
  1922. X    }
  1923. X    }
  1924. X
  1925. X    /* switch roles or finish if slave has no work */
  1926. X
  1927. X    return(isok("H") == YES ? (talk("HY"),DONE) : SLAVE);
  1928. X}
  1929. X
  1930. X/* slave - process remote work; accept H and S requests only */
  1931. X
  1932. Xhidden int slave()
  1933. X{
  1934. X    register char *cmnd;
  1935. X    register work *wrk;
  1936. X
  1937. X    for (;;) {
  1938. X    switch ((cmnd = hear())[0]) {
  1939. X    case 'S':                /* master wants to send */
  1940. X        log("REQUESTED (%s)",cmnd);        /* log the request */
  1941. X        wrk = rmtwork(cmnd);        /* parse the request */
  1942. X        talk("SY");                /* say ok */
  1943. X        getwork(wrk);            /* receive work */
  1944. X        talk("CY");                /* we never copy */
  1945. X        log("COPY (SUCCEEDED)");
  1946. X        break;
  1947. X    case 'H':                /* master is out of work */
  1948. X        return(scanwork() ? (talk("HN"),MASTER) : (talk("HY"),DONE));
  1949. X    default:
  1950. X        talk(strcons("%cN",cmnd[0]));    /* refuse other type of work */
  1951. X        break;
  1952. X    }
  1953. X    }
  1954. X}
  1955. END_OF_switcher.c
  1956. if test 4041 -ne `wc -c <switcher.c`; then
  1957.     echo shar: \"switcher.c\" unpacked with wrong size!
  1958. fi
  1959. # end of overwriting check
  1960. fi
  1961. if test -f unalias.c -a "${1}" != "-c" ; then 
  1962.   echo shar: Will not over-write existing file \"unalias.c\"
  1963. else
  1964. echo shar: Extracting \"unalias.c\" \(4581 characters\)
  1965. sed "s/^X//" >unalias.c <<'END_OF_unalias.c'
  1966. X/*++
  1967. X/* NAME
  1968. X/*    unalias 3
  1969. X/* SUMMARY
  1970. X/*    alias processing
  1971. X/* PROJECT
  1972. X/*    pc-mail
  1973. X/* PACKAGE
  1974. X/*    smail
  1975. X/* SYNOPSIS
  1976. X/*    char **unalias(namevec)
  1977. X/*    char **namevec;
  1978. X/* DESCRIPTION
  1979. X/*    unalias() takes an array of string pointers and returns a vector 
  1980. X/*    with string pointers to their alias expansions. The resulting 
  1981. X/*    vector is in static memory.
  1982. X/*
  1983. X/*    After alias expansion, all addresses are sorted and duplicate 
  1984. X/*    names are eliminated. The algorithms for alias expansion and 
  1985. X/*    duplicate elimination are case-insensitive. 
  1986. X/*
  1987. X/*    unalias() accesses the alias data base through the ascf ASCII
  1988. X/*    filter.
  1989. X/* DIAGNOSTICS
  1990. X/*    unalias() returns a null pointer in case of memory-allocation problems.
  1991. X/*
  1992. X/*    unalias() terminates prematurely when the alias expansion has 
  1993. X/*    produced BUFSIZ recipients. This provides some defense against 
  1994. X/*    cycles in the alias data base. It is up to the caller to 
  1995. X/*    recognize this condition.
  1996. X/* BUGS
  1997. X/*    The overflow/cycle detection algorithm is inelegant.
  1998. X/* FILES
  1999. X/*    Alias data base in spool directory
  2000. X/* AUTHOR(S)
  2001. X/*      W.Z. Venema
  2002. X/*      Eindhoven University of Technology
  2003. X/*      Department of Mathematics and Computer Science
  2004. X/*      Den Dolech 2, P.O. Box 513, 5600 MB Eindhoven, The Netherlands
  2005. X/* CREATION DATE
  2006. X/*    Wed Apr  6 20:21:35 MET 1988
  2007. X/* LAST MODIFICATION
  2008. X/*    Wed Apr  6 20:21:35 MET 1988
  2009. X/* VERSION/RELEASE
  2010. X/*    1.0
  2011. X/*--*/
  2012. X
  2013. X#include "defs.h"
  2014. X#include "hsearch.h"
  2015. X#include "path.h"
  2016. X#include "ascf.h"
  2017. X
  2018. X/* forward declarations */
  2019. X
  2020. Xhidden int hash_alias();
  2021. Xhidden void sort_alias();
  2022. Xhidden void uniq_alias();
  2023. Xhidden char **find_alias();
  2024. X
  2025. X/* unalias - replace aliases by their equivalents */
  2026. X
  2027. Xpublic char **unalias(names)
  2028. Xchar **names;
  2029. X{
  2030. X    static int dohash = 1;        /* hash table not yet made */
  2031. X    static char *recp[BUFSIZ+1];    /* the result of alias expansion */
  2032. X    char **stop = recp+BUFSIZ;        /* overflow limit */
  2033. X
  2034. X    if (dohash && (dohash = hash_alias())) /* build the hash table */
  2035. X    return(0);
  2036. X    if (stop > find_alias(names,recp,stop)) { /* build vector of addresses */
  2037. X    sort_alias(recp);        /* sort the recp list */
  2038. X    uniq_alias(recp);        /* squeeze out identical addresses */
  2039. X    }
  2040. X    return(recp);
  2041. X}
  2042. X
  2043. X/* hash_alias - copy alias data base to hash table */
  2044. X
  2045. Xhidden int hash_alias()
  2046. X{
  2047. X    register FILE *fp;
  2048. X    char buf[BUFSIZ];
  2049. X
  2050. X    /* initialize the hash table */
  2051. X
  2052. X    if (hcreate(BUFSIZ) == 0)
  2053. X    return(-1);
  2054. X
  2055. X    /*
  2056. X    * Lines in the alias data base are of the form
  2057. X    *
  2058. X    *    <left-hand part>    <right-hand part>
  2059. X    *
  2060. X    * where the l.h. part is an alias, and the r.h. part one or more
  2061. X    * words. Of course, those words can be aliases. The order in which
  2062. X    * aliases are defined is not important. The alias data base is used
  2063. X    * only after it has been loaded into memory.
  2064. X    * 
  2065. X    * Each l.h. part is used as the key for finding the r.h. part in the
  2066. X    * hash table. The r.h. part is stored as a vector of pointers to strings.
  2067. X    */
  2068. X
  2069. X    if (fp = ascopen(aliases(),"r")) {        /* read through ASCII filter */
  2070. X    while (fgets(buf,BUFSIZ,fp)) {        /* read alias entry */
  2071. X        register char **cpp;
  2072. X        ENTRY e;
  2073. X        if ((cpp = strvec(buf,", \t\r\n")) == 0) /* split alias entry */
  2074. X        return(-1);
  2075. X        if ((e.key = *cpp)            /* left-hand part exists */
  2076. X        && (e.data = (char *) (cpp+1))    /* right-hand part exists */
  2077. X        && (hsearch(e,ENTER) == 0))        /* enter hash table */
  2078. X        return(-1);
  2079. X    }
  2080. X    ascclose(fp);
  2081. X    }
  2082. X    return(0);
  2083. X}
  2084. X
  2085. X/* find_alias - recursively expand aliases */
  2086. X
  2087. Xhidden char **find_alias(from,to,stop)
  2088. Xchar **from;
  2089. Xregister char **to;
  2090. Xregister char **stop;
  2091. X{
  2092. X    register char **cpp;
  2093. X    register ENTRY *sp;
  2094. X
  2095. X    /* recursively replace aliases, but don't crash in case of cycles */
  2096. X
  2097. X    for (cpp = from; *cpp && (to < stop); cpp++) {
  2098. X    ENTRY e;
  2099. X    e.key = *cpp;
  2100. X    if (sp = hsearch(e,FIND)) {
  2101. X        to = find_alias((char **)sp->data,to,stop);
  2102. X    } else {
  2103. X        *to++ = *cpp;
  2104. X    }
  2105. X    }
  2106. X    *to = 0;
  2107. X    return(to);
  2108. X}
  2109. X
  2110. X/* Istrcmp - interface between qsort and istrcmp */
  2111. X
  2112. Xhidden int Istrcmp(p1,p2)
  2113. Xchar **p1,**p2;
  2114. X{
  2115. X    return(istrcmp(*p1,*p2));
  2116. X}
  2117. X
  2118. X/* sort_alias - sort the addresses after alias substitutions */
  2119. X
  2120. Xhidden void sort_alias(to)
  2121. Xchar **to;
  2122. X{
  2123. X     register char **cpp;
  2124. X     int istrcmp();
  2125. X
  2126. X     /* find out length of the list */
  2127. X
  2128. X     for (cpp = to; *cpp; cpp++)
  2129. X    /* void */ ;
  2130. X
  2131. X     /* sort the list */
  2132. X
  2133. X    qsort((char *)to,cpp-to,sizeof(*to),Istrcmp);
  2134. X}
  2135. X
  2136. X/* uniq_alias - collapse sequences of identical addresses */
  2137. X
  2138. Xhidden void uniq_alias(to)
  2139. Xchar **to;
  2140. X{
  2141. X    register char **in = to;
  2142. X    register char **out = to;
  2143. X
  2144. X    while (*out = *in) {
  2145. X    while (*++in && istrcmp(*out,*in) == 0) {
  2146. X        /* void */ ;
  2147. X    }
  2148. X    ++out;
  2149. X    }
  2150. X}
  2151. END_OF_unalias.c
  2152. if test 4581 -ne `wc -c <unalias.c`; then
  2153.     echo shar: \"unalias.c\" unpacked with wrong size!
  2154. fi
  2155. # end of overwriting check
  2156. fi
  2157. echo shar: End of archive 5 \(of 8\).
  2158. cp /dev/null ark5isdone
  2159. MISSING=""
  2160. for I in 1 2 3 4 5 6 7 8 ; do
  2161.     if test ! -f ark${I}isdone ; then
  2162.     MISSING="${MISSING} ${I}"
  2163.     fi
  2164. done
  2165. if test "${MISSING}" = "" ; then
  2166.     echo You have unpacked all 8 archives.
  2167.     rm -f ark[1-9]isdone
  2168. else
  2169.     echo You still need to unpack the following archives:
  2170.     echo "        " ${MISSING}
  2171. fi
  2172. ##  End of shell archive.
  2173. exit 0
  2174. -- 
  2175. uucp:    mcvax!eutrc3!wswietse    | Eindhoven University of Technology
  2176. bitnet:    wswietse@heithe5    | Dept. of Mathematics and Computer Science
  2177. surf:    tuerc5::wswietse    | Eindhoven, The Netherlands.
  2178.